package cn.yzj.openapi.service.impl;

import cn.yzj.http.YzjHttp;
import cn.yzj.http.YzjHttpResult;
import cn.yzj.openapi.bo.EpidemicAreaBO;
import cn.yzj.openapi.bo.EpidemicCityBO;
import cn.yzj.openapi.converter.EpidemicConverter;
import cn.yzj.openapi.dto.EpidemicQueryDTO;
import cn.yzj.openapi.enums.error.EpidemicErrorEnums;
import cn.yzj.openapi.enums.method.EpidemicMethodEnums;
import cn.yzj.openapi.exception.OpenApiException;
import cn.yzj.openapi.service.EpidemicService;
import cn.yzj.openapi.vo.EpidemicVO;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.cache.Cache;
import io.jsonwebtoken.lang.Collections;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @author gzkemays
 * @since 2022/4/14 11:14
 */
@Service
public class EpidemicServiceImpl implements EpidemicService {
  @Resource(name = "epidemicCache")
  Cache<String, Object> epidemicCache;

  @Override
  public List<EpidemicVO> getEpidemic(EpidemicQueryDTO dto) {
    return findPositionEpidemic(getAllPositionEpidemic(), dto);
  }

  @Override
  public List<EpidemicVO> getEpidemic(String position) {
    List<EpidemicAreaBO> allEpidemic = getAllPositionEpidemic();
    List<EpidemicVO> list = new ArrayList<>();
    if (CHINA_VOCABULARY.contains(position)) {
      position = CHINA;
    }
    for (EpidemicAreaBO areaBO : allEpidemic) {
      String area = areaBO.getArea();
      if (area.contains(position)) {
        list.add(EpidemicConverter.INSTANCE.areaBoConverterVo(areaBO));
      }
      List<EpidemicCityBO> subList = areaBO.getSubList();
      if (!Collections.isEmpty(subList)) {
        for (EpidemicCityBO cityBO : subList) {
          String city = cityBO.getCity();
          if (city.contains(position)) {
            list.add(EpidemicConverter.INSTANCE.cityBoConverterVo(cityBO));
          }
        }
      }
    }
    if (list.isEmpty()) {
      throw OpenApiException.epidemicException(EpidemicErrorEnums.EPIDEMIC_IS_NOT_FOUND);
    }
    return list;
  }

  private List<EpidemicVO> findPositionEpidemic(
      List<EpidemicAreaBO> epidemics, EpidemicQueryDTO dto) {
    String area = dto.getArea();
    String city = dto.getCity();
    List<EpidemicAreaBO> areaBos = new ArrayList<>();
    List<EpidemicCityBO> cityBos = new ArrayList<>();
    for (EpidemicAreaBO epidemic : epidemics) {
      if (epidemic.getArea().contains(area)) {
        if (Objects.isNull(city)) {
          areaBos.add(epidemic);
        } else {
          List<EpidemicCityBO> subList = epidemic.getSubList();
          for (EpidemicCityBO epidemicCity : subList) {
            if (epidemicCity.getCity().contains(city)) {
              cityBos.add(epidemicCity);
            }
          }
        }
      }
    }

    if (areaBos.isEmpty() && cityBos.isEmpty()) {
      throw OpenApiException.epidemicException(EpidemicErrorEnums.EPIDEMIC_IS_NOT_FOUND);
    }
    if (Objects.isNull(city)) {
      return EpidemicConverter.INSTANCE.areaBosConverterVos(areaBos);
    } else {
      return EpidemicConverter.INSTANCE.cityBosConverterVos(cityBos);
    }
  }

  /**
   * 获取所有疫情数据
   *
   * @return 疫情数据
   */
  private List<EpidemicAreaBO> getAllPositionEpidemic() {
    Object ifPresent = epidemicCache.getIfPresent(EPIDEMIC_ALL_DATA);
    if (ifPresent == null) {
      YzjHttpResult send = YzjHttp.createGet(BAIDU_EPIDEMIC_SOURCE).send();
      Document document = send.getDocument();
      Elements script = document.getElementsByTag("script");
      List<EpidemicAreaBO> bos = new ArrayList<>();
      for (Element element : script) {
        if ("application/json".equals(element.attr("type"))) {
          String text = element.html();
          JSONObject jsonObject = JSONObject.parseObject(text);
          JSONObject component = jsonObject.getJSONArray("component").getJSONObject(0);
          for (EpidemicMethodEnums value : EpidemicMethodEnums.values()) {
            if (!value.equals(EpidemicMethodEnums.CHINA)) {
              JSONArray caseList = component.getJSONArray(value.getModeKey());
              for (Object o : caseList) {
                EpidemicAreaBO epidemicAreaBO =
                    JSONObject.toJavaObject((JSONObject) o, EpidemicAreaBO.class);
                bos.add(epidemicAreaBO);
              }
            } else {
              JSONObject json = component.getJSONObject(value.getModeKey());
              EpidemicAreaBO china = component.getObject(value.getModeKey(), EpidemicAreaBO.class);
              china.setArea(value.getPosition());
              china.setCrued(json.getString("cured"));
              bos.add(china);
            }
          }
          break;
        }
      }
      epidemicCache.put(EPIDEMIC_ALL_DATA, bos);
      return bos;
    }
    return (List<EpidemicAreaBO>) ifPresent;
  }
}
